// Sets (集合) 示例
// 演示 Pascal 中集合的各种用法
program p_9_sets;

{$mode objfpc}{$H+}
// {$mode objfpc} 启用 Object Pascal 模式
// {$H+} 启用长字符串支持（AnsiString）

// 引入单元文件
uses
  SysUtils;  // 系统工具单元，包含常用的系统函数

// 定义集合类型
type
  // 定义数字集合类型 (0-9)
  TDigit = 0..9;
  TDigitSet = set of TDigit;
  
  // 定义字符集合类型 (A-Z)
  TLetter = 'A'..'Z';
  TLetterSet = set of TLetter;
  
  // 定义枚举集合类型
  TColor = (Red, Green, Blue, Yellow, Purple, Orange);
  TColorSet = set of TColor;
  
  // 定义布尔集合类型
  TBoolSet = set of Boolean;

// 函数：将数字集合转换为字符串
function DigitSetToString(s: TDigitSet): String;
var
  i: TDigit;
  resultStr: String;
begin
  resultStr := '[';
  for i := 0 to 9 do
  begin
    if i in s then
    begin
      if Length(resultStr) > 1 then
        resultStr := resultStr + ', ';
      resultStr := resultStr + IntToStr(i);
    end;
  end;
  resultStr := resultStr + ']';
  DigitSetToString := resultStr;
end;

// 函数：将字符集合转换为字符串
function LetterSetToString(s: TLetterSet): String;
var
  c: TLetter;
  resultStr: String;
begin
  resultStr := '[';
  for c := 'A' to 'Z' do
  begin
    if c in s then
    begin
      if Length(resultStr) > 1 then
        resultStr := resultStr + ', ';
      resultStr := resultStr + c;
    end;
  end;
  resultStr := resultStr + ']';
  LetterSetToString := resultStr;
end;

// 函数：将颜色枚举集合转换为字符串
function ColorSetToString(s: TColorSet): String;
var
  color: TColor;
  resultStr: String;
  colorNames: array[TColor] of String;
begin
  colorNames[Red] := 'Red';
  colorNames[Green] := 'Green';
  colorNames[Blue] := 'Blue';
  colorNames[Yellow] := 'Yellow';
  colorNames[Purple] := 'Purple';
  colorNames[Orange] := 'Orange';
  
  resultStr := '[';
  for color := Red to Orange do
  begin
    if color in s then
    begin
      if Length(resultStr) > 1 then
        resultStr := resultStr + ', ';
      resultStr := resultStr + colorNames[color];
    end;
  end;
  resultStr := resultStr + ']';
  ColorSetToString := resultStr;
end;

// 函数：将布尔集合转换为字符串
function BoolSetToString(s: TBoolSet): String;
var
  resultStr: String;
begin
  resultStr := '[';
  if False in s then
    resultStr := resultStr + 'False';
  if (False in s) and (True in s) then
    resultStr := resultStr + ', ';
  if True in s then
    resultStr := resultStr + 'True';
  resultStr := resultStr + ']';
  BoolSetToString := resultStr;
end;

// 所有变量声明移到这里
var
  digits: TDigitSet;
  emptySet: TDigitSet;
  fullSet: TDigitSet;
  setA: TDigitSet;
  setB: TDigitSet;
  union: TDigitSet;
  intersection: TDigitSet;
  difference: TDigitSet;
  vowels: TLetterSet;
  wordLetters: TLetterSet;
  colors: TColorSet;
  boolSet: TBoolSet;
  i: TDigit;
  c: TLetter;
  color: TColor;

// 程序主入口
begin
  WriteLn('=== Pascal 集合示例 ===');
  WriteLn;
  
  // 1. 基本集合声明和初始化
  WriteLn('1. 基本集合声明和初始化:');
  digits := [1, 2, 3, 5, 8];  // 用方括号初始化集合
  WriteLn('  digits集合包含: ', DigitSetToString(digits));
  
  // 2. 空集合和全集合
  WriteLn('2. 空集合和全集合:');
  emptySet := [];  // 空集合
  WriteLn('  空集合: ', DigitSetToString(emptySet));
  
  fullSet := [0..9];  // 包含所有数字的集合
  WriteLn('  全数字集合: ', DigitSetToString(fullSet));
  
  WriteLn;
  
  // 3. 集合成员测试
  WriteLn('3. 集合成员测试:');
  if 5 in digits then
    WriteLn('  5 在 digits 集合中')
  else
    WriteLn('  5 不在 digits 集合中');
    
  if 4 in digits then
    WriteLn('  4 在 digits 集合中')
  else
    WriteLn('  4 不在 digits 集合中');
  
  WriteLn;
  
  // 4. 集合基本操作
  WriteLn('4. 集合基本操作:');
  setA := [1, 2, 3, 4, 5];
  setB := [4, 5, 6, 7, 8];
  
  WriteLn('  集合A: ', DigitSetToString(setA));
  WriteLn('  集合B: ', DigitSetToString(setB));
  
  // 并集
  union := setA + setB;
  WriteLn('  A ∪ B (并集): ', DigitSetToString(union));
  
  // 交集
  intersection := setA * setB;
  WriteLn('  A ∩ B (交集): ', DigitSetToString(intersection));
  
  // 差集
  difference := setA - setB;
  WriteLn('  A - B (差集): ', DigitSetToString(difference));
  
  WriteLn;
  
  // 5. 字符集合
  WriteLn('5. 字符集合:');
  vowels := ['A', 'E', 'I', 'O', 'U'];
  WriteLn('  元音字母集合: ', LetterSetToString(vowels));
  
  wordLetters := ['H', 'E', 'L', 'O'];
  WriteLn('  单词"HELO"的字母集合: ', LetterSetToString(wordLetters));
  
  // 集合关系测试
  if vowels >= ['A', 'E'] then
    WriteLn('  集合包含元音字母A和E');
  
  WriteLn;
  
  // 6. 枚举集合
  WriteLn('6. 枚举集合:');
  colors := [Red, Green, Blue];
  WriteLn('  基本颜色集合: ', ColorSetToString(colors));
  
  // 添加元素到集合
  Include(colors, Yellow);
  WriteLn('  添加黄色后: ', ColorSetToString(colors));
  
  // 从集合中移除元素
  Exclude(colors, Green);
  WriteLn('  移除绿色后: ', ColorSetToString(colors));
  
  WriteLn;
  
  // 7. 集合遍历
  WriteLn('7. 集合遍历:');
  Write('  vowels集合中的元素: ');
  for c := 'A' to 'Z' do
  begin
    if c in vowels then
      Write(c, ' ');
  end;
  WriteLn;
  
  WriteLn;
  
  // 8. 布尔集合
  WriteLn('8. 布尔集合:');
  boolSet := [True];  // 只包含True的集合
  WriteLn('  boolSet: ', BoolSetToString(boolSet));
  
  // 布尔集合操作
  boolSet := boolSet + [False];  // 添加False
  WriteLn('  添加False后: ', BoolSetToString(boolSet));
  
  WriteLn;
  WriteLn('演示了 Pascal 中集合的各种用法');
  
  // 等待用户按键，防止程序窗口立即关闭
  ReadLn;
end.